package cn.janus.service.impl;

import cn.hutool.core.lang.Assert;
import cn.janus.entity.Roles;
import cn.janus.entity.UserRoles;
import cn.janus.entity.Users;
import cn.janus.eum.ErrorMessageEum;
import cn.janus.eum.RoleEnum;
import cn.janus.mapper.UserMapper;
import cn.janus.pojo.dto.UserDTO;
import cn.janus.service.IRolesService;
import cn.janus.service.IUserRolesService;
import cn.janus.service.IUserService;
import cn.janus.util.JwtUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author janus
 * @since 2024-07-30
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, Users> implements IUserService {
    @Autowired
    private IUserRolesService userRolesService;
    @Autowired
    private IRolesService rolesService;
    @Autowired
    private JwtUtil jwtUtil;


    @Override
    public void saveUser(UserDTO userDTO) {
        Users user = this.getOne(new LambdaQueryWrapper<Users>().eq(Users::getName, userDTO.getUsername()));
        Assert.isTrue(Objects.isNull(user), ErrorMessageEum.USER_EXIST.getMessage());

        user = new Users();
        user.setId(UUID.randomUUID().toString());
        user.setName(userDTO.getUsername());
        user.setPassword(BCrypt.hashpw(userDTO.getPassword(), BCrypt.gensalt()));
        this.save(user);

        Map<String, Integer> roles = rolesService.list().stream().collect(Collectors.toMap(Roles::getRoleName, Roles::getRoleId));

        UserRoles userRole = new UserRoles();
        userRole.setUserRoleId(UUID.randomUUID().toString());
        userRole.setUserId(user.getId());
        Integer i = roles.get(RoleEnum.USER.getRole());
        Assert.isTrue(Objects.nonNull(i), "改角色不存在");
        userRole.setRoleId(i);
        userRolesService.save(userRole);
    }

    @Override
    public String login(UserDTO userDTO) {
        Users user = this.getOne(new LambdaQueryWrapper<Users>().eq(Users::getName, userDTO.getUsername()));
        Assert.isFalse(Objects.isNull(user), ErrorMessageEum.LONGIN_USER_NOT_EXIST.getMessage());
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        Assert.isTrue(passwordEncoder.matches(
                userDTO.getPassword(), user.getPassword()), ErrorMessageEum.PASSWORD_INCORRECT.getMessage());

        Set<Integer> roleIds = userRolesService
                .list(new LambdaQueryWrapper<UserRoles>().eq(UserRoles::getUserId, user.getId()))
                .stream().map(UserRoles::getRoleId).collect(Collectors.toSet());
        Set<String> roles = rolesService
                .list(new LambdaQueryWrapper<Roles>().in(Roles::getRoleId, roleIds))
                .stream().map(Roles::getRoleName).collect(Collectors.toSet());

        return jwtUtil.generateToken(user.getId(), roles);
    }
}
